package com.atguigu.gmall.seckill.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.seckill.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.seckill.mapper.SeckillMapper;
import com.atguigu.gmall.seckill.pojo.SeckillOrder;
import com.atguigu.gmall.seckill.pojo.UserRecode;
import com.atguigu.gmall.seckill.service.SeckillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author jzq
 * @create 2021-07-14 19:03
 */
@Service
public class SeckillServiceImpl implements SeckillService {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 秒杀的列表
     * @param time
     * @return
     */
    @Override
    public List<SeckillGoods> getSeckillGoods(String time) {
        List values = redisTemplate.boundHashOps("SeckillGoods_" + time).values();
        return values;
    }

    /**
     * 商品详情
     * @param time
     * @param id
     * @return
     */

    @Override
    public SeckillGoods getSeckillGood(String time, String id) {
        SeckillGoods o = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(id);
        return o;
    }

    /**
     *用户排队下单
     * @param time
     * @param skuId
     * @param userId
     * @return
     */
      @Autowired
      private RabbitService rabbitService;
    @Override
    public UserRecode addOrder(String time, String skuId, String userId) {
     //记录用户的排队信息
        UserRecode userRecode = new UserRecode();
        //防止用户重复排队
        Long increment = redisTemplate.boundValueOps("SeckillUserQueue_" + userId).increment(1);
        if (increment >1){
             userRecode.setStatus(3);
             userRecode.setMsg("重复排队");
             return  userRecode;
        }
         userRecode.setUsername(userId);
        userRecode.setCreateTime(new Date());
        //设置状态为排队中
        userRecode.setStatus(1);
        userRecode.setGoodsId(skuId);
        userRecode.setTime(time);
        userRecode.setNum(1);
        //将用户的排队的信息存入redis
        redisTemplate.boundValueOps("SeckillStatus_" + userId).set(userRecode);
        //发送消息进行异步下单
          rabbitService.sendMessage("seckill_exchange","seckill.order.add", JSONObject.toJSONString(userRecode));
         return userRecode;
    }

    /**
     * 查询用户排队信息
     * @param userId
     * @return
     */

    @Override
    public UserRecode getUserRecode(String userId) {
        UserRecode o = (UserRecode) redisTemplate.boundValueOps("SeckillStatus_" + userId).get();
        return o ;
    }

    /**
     * 查询秒杀订单列表
     * @param username
     * @param orderId
     * @return
     */

    @Override
    public List<SeckillOrder> getSeckillOrderList(String username, String orderId) {
       if (StringUtils.isEmpty(orderId)){
           //查询所有的秒杀列表
           return redisTemplate.boundHashOps("SeckillOrder_" + username).values();
       }else {
           List<SeckillOrder> seckillOrders = new ArrayList<>();
           //查询指定的秒杀订单详情
           SeckillOrder  o = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder_" + username).get(orderId);
           seckillOrders.add(o);
           return seckillOrders;

       }
    }

    /**
     * 支付成功
     * @param map
     */
    @Resource
    private SeckillMapper seckillMapper;
    @Override
    public void paySuccess(Map<String, String> map) {
        //获取微信附加参数
        String attach = map.get("attach");
        //判断是否为空，为空则为支付宝支付
        if (StringUtils.isEmpty(attach)){
            attach = map.get("passback_params");
        }
        //类型转换
        Map<String,String> attachMap = JSONObject.parseObject(attach, Map.class);
        String username = attachMap.get("username");
        String outTradeNo = map.get("out_trade_no");
        //从rdis中获取订单消息
        SeckillOrder  seckillOrder = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder_" + username).get(outTradeNo);
        //判断前置状态
        if (seckillOrder!= null && seckillOrder.getStatus().equals("0")){
            //修改订单状态为已支付
            seckillOrder.setStatus("1");
            seckillOrder.setPayTime(new Date());
            String transaction_id;
            transaction_id = map.get("transaction_id");
            if (StringUtils.isEmpty(transaction_id)){
                transaction_id = map.get("trade_no");
            }
            seckillOrder.setOutTradeNo(transaction_id);
            //修改redis订单状态
            redisTemplate.boundHashOps("SeckillOrder_" + username).put(outTradeNo,seckillOrder);
            //将订单的信息存入数据库
             seckillMapper.insert(seckillOrder);
             //排队标识删除
            redisTemplate.delete("SeckillUserQueue_" + username);
            //排队状态删除
            redisTemplate.delete("SeckillStatus_" + username);

        }
    }

    /**
     * 支付失败
     * @param map
     */
    @Override
    public void payFail(Map<String, String> map) {
        //获取微信附加参数
        String attach = map.get("attach");
        //判断是否为空，为空则为支付宝支付
        if (StringUtils.isEmpty(attach)){
            attach = map.get("passback_params");
        }
        //类型转换
        Map<String,String> attachMap = JSONObject.parseObject(attach, Map.class);
        String username = attachMap.get("username");
        String outTradeNo = map.get("out_trade_no");
        //从rdis中获取订单消息
        SeckillOrder  seckillOrder = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder_" + username).get(outTradeNo);
        //判断前置状态
        if (seckillOrder!= null && seckillOrder.getStatus().equals("0")){
            //修改订单状态为失败
            seckillOrder.setStatus("2");
            //修改redis订单状态
            redisTemplate.boundHashOps("SeckillOrder_" + username).put(outTradeNo,seckillOrder);
            //将订单的信息存入数据库
            seckillMapper.insert(seckillOrder);
            //库存回滚
            UserRecode  userRecode = (UserRecode) redisTemplate.boundValueOps("SeckillStatus_" + username).get();
            rollBackSeckillGoodsNum(userRecode.getGoodsId(),userRecode.getTime(),userRecode.getNum());
            //排队标识删除
            redisTemplate.delete("SeckillUserQueue_" + username);
            //排队状态删除
            redisTemplate.delete("SeckillStatus_" + username);

        }
   }
    @Resource
    private SeckillGoodsMapper seckillGoodsMapper;

    /**
     * 回滚库存
     * @param skuId
     * @param time
     * @param num
     */
    private void rollBackSeckillGoodsNum(String skuId, String time, Integer num){

    //从redis中获取商品
        SeckillGoods  seckillGoods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(skuId);
        //校验
        if (seckillGoods == null){
            seckillGoodsMapper.updateSeckillGoodsStock(skuId, num);
        }else {
            //更新redis的数据
            String[] seckillGoodsQueue = getSeckillGoodsQueue(skuId, num);
            redisTemplate.boundListOps("seckillGoodsQueue_" + skuId).leftPushAll(seckillGoodsQueue);
            //回滚库存
            redisTemplate.boundHashOps("SeckillGoodsStockNum").increment(skuId,num);
        }


    }

    /**
     *商品长度数组
     * @param goodsId
     * @param stockCount
     * @return
     */
    private String[] getSeckillGoodsQueue(String goodsId, Integer stockCount){
        //构建一个库存长度的数组
        String[] ids = new String[stockCount];
        //元素填充
        for (int i = 0; i < stockCount; i++) {
            ids[i] = goodsId;
        }
        //返回数据
        return ids;
    }
}
